﻿using System;
using System.ComponentModel.Design;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace SedionFormDesigner.Service
{
    /// <summary>
    ///  按钮服务(快捷键)
    /// </summary>
    public class SedionMenuCommandService : System.ComponentModel.Design.IMenuCommandService
    {
        private IDesignerHost host;
        // 按钮集合
        private Hashtable commands;
        // 按钮项的值映射到DesignerVerb的键
        private Hashtable menuItemsFromVerbs;
        // DesignerVerb的值映射到按钮项的键
        private Hashtable verbsFromMenuItems;
        // 对所有设计器都有效的verbs
        private ArrayList globalVerbs;
        // 表示快捷菜单
        private ContextMenu cm;
        // 通过上一个选项清楚本地verbs
        private IComponent lastSelection;

        public SedionMenuCommandService(IDesignerHost host)
        {
            this.host = host;
        }

        private void menuItem_Click(object sender, EventArgs e)
        {
            MenuItem key = sender as MenuItem;
            DesignerVerb verb = verbsFromMenuItems[key] as DesignerVerb;
            verb.Invoke();
        }

        private void AddLocalVerb(DesignerVerb verb)
        {
            if ((globalVerbs == null) || (globalVerbs.Contains(verb)))
            {
                if (cm == null)
                {
                    cm = new ContextMenu();
                    verbsFromMenuItems = new Hashtable();
                    menuItemsFromVerbs = new Hashtable();
                }

                MenuItem menuItem = new MenuItem(verb.Text);
                menuItem.Click += new EventHandler(menuItem_Click);
                verbsFromMenuItems.Add(menuItem, verb);
                menuItemsFromVerbs.Add(verb, menuItem);
                cm.MenuItems.Add(menuItem);
            }
        }

        private void RemoveLocalVerb(DesignerVerb verb)
        {
            if ((globalVerbs == null) || (!globalVerbs.Contains(verb)))
            {
                if (cm != null)
                {
                    MenuItem key = menuItemsFromVerbs[verb] as MenuItem;
                    verbsFromMenuItems.Remove(key);
                    menuItemsFromVerbs.Remove(verb);
                    cm.MenuItems.Remove(key);
                }
            }
        }

        #region IMenuCommandService 成员

        /// <summary>
        ///  添加按钮
        /// </summary>
        public void AddCommand(System.ComponentModel.Design.MenuCommand command)
        {
            if (commands == null)
                commands = new Hashtable();

            if (FindCommand(command.CommandID) == null)
                commands.Add(command.CommandID, command);
        }

        /// <summary>
        ///  添加verb
        /// </summary>
        public void AddVerb(System.ComponentModel.Design.DesignerVerb verb)
        {
            if (globalVerbs == null)
                globalVerbs = new ArrayList();

            globalVerbs.Add(verb);

            if (cm == null)
            {
                cm = new ContextMenu();
                verbsFromMenuItems = new Hashtable();
                menuItemsFromVerbs = new Hashtable();
            }

            MenuItem menuItem = new MenuItem(verb.Text);
            menuItem.Click += new EventHandler(menuItem_Click);
            verbsFromMenuItems.Add(menuItem, verb);
            menuItemsFromVerbs.Add(verb, menuItem);
            cm.MenuItems.Add(menuItem);
        }

        /// <summary>
        ///  找到按钮
        /// </summary>
        public System.ComponentModel.Design.MenuCommand FindCommand(System.ComponentModel.Design.CommandID commandID)
        {
            if (commands != null)
            {
                MenuCommand command = commands[commandID] as MenuCommand;
                if (command != null)
                    return command;
            }

            return null;
        }

        /// <summary>
        ///  只执行已经添加的按钮
        /// </summary>
        public bool GlobalInvoke(System.ComponentModel.Design.CommandID commandID)
        {
            MenuCommand command = FindCommand(commandID);
            if (command != null)
            {
                command.Invoke();
                return true;
            }
            return false;
        }

        /// <summary>
        ///  移除按钮
        /// </summary>
        public void RemoveCommand(System.ComponentModel.Design.MenuCommand command)
        {
            if (commands != null)
                commands.Remove(command.CommandID);
        }

        /// <summary>
        ///  移除verb影响整个设计器
        /// </summary>
        public void RemoveVerb(System.ComponentModel.Design.DesignerVerb verb)
        {
            if (globalVerbs != null)
            {
                globalVerbs.Remove(verb);

                if (cm != null)
                {
                    MenuItem key = menuItemsFromVerbs[verb] as MenuItem;
                    verbsFromMenuItems.Remove(key);
                    menuItemsFromVerbs.Remove(verb);
                    cm.MenuItems.Remove(key);
                }
            }
        }

        /// <summary>
        ///  在指定位置显示指定的快捷方式
        /// </summary>
        public void ShowContextMenu(System.ComponentModel.Design.CommandID menuID, int x, int y)
        {
            ISelectionService selectionService = host.GetService(typeof(ISelectionService)) as ISelectionService;

            // 如果是同一个组件的最后次右击,那么不需要改变
            if ((lastSelection != null) && (lastSelection != selectionService.PrimarySelection))
            {
                foreach (DesignerVerb verb in host.GetDesigner(lastSelection).Verbs)
                {
                    RemoveLocalVerb(verb);
                }
            }

            // 为新选择项更新verb
            if (lastSelection != selectionService.PrimarySelection)
            {
                foreach (DesignerVerb verb in host.GetDesigner(selectionService.PrimarySelection as IComponent).Verbs)
                {
                    AddLocalVerb(verb);
                }
            }

            // 显示快捷点
            if (cm != null)
            {
                Control ps = selectionService.PrimarySelection as Control;
                Point point = ps.PointToScreen(new Point(0, 0));
                cm.Show(ps, new Point(x - point.X, y - point.Y));
            }

            // 记录下来等待下次再移除
            // 因为无法确定右击已经结束了
            lastSelection = selectionService.PrimarySelection as IComponent;
        }

        public System.ComponentModel.Design.DesignerVerbCollection Verbs
        {
            get
            {
                ISelectionService selectionService = host.GetService(typeof(ISelectionService)) as ISelectionService;
                ArrayList currentVerbs;
                if (globalVerbs != null)
                    currentVerbs = new ArrayList(globalVerbs);
                else
                    currentVerbs = new ArrayList();

                foreach (DesignerVerb verb in host.GetDesigner(selectionService.PrimarySelection as IComponent).Verbs)
                {
                    if (!currentVerbs.Contains(verb))
                        currentVerbs.Add(verb);
                }

                if (currentVerbs.Count > 0)
                {
                    DesignerVerb[] ret = new DesignerVerb[currentVerbs.Count];
                    currentVerbs.CopyTo(ret);
                    return new DesignerVerbCollection(ret);
                }
                else
                    return new DesignerVerbCollection();
            }
        }

        #endregion
    }
}
